<?php
// +-----------------+------------------+------+-----+---------+----------------+
// | Field           | Type             | Null | Key | Default | Extra          |
// +-----------------+------------------+------+-----+---------+----------------+
// | id              | int(11)          | NO   | PRI | NULL    | auto_increment |
// | title           | varchar(50)      | NO   |     |         |                |
// | slug            | varchar(50)      | NO   |     |         |                |
// | parent_id       | varchar(255)     | YES  |     | 0       |                |
// | pc_banner_id    | int(11) unsigned | YES  |     | 0       |                |
// | wap_banner_id   | int(11) unsigned | YES  |     | 0       |                |
// | seo_description | varchar(255)     | NO   |     |         |                |
// | seo_keywords    | varchar(255)     | NO   |     |         |                |
// | index_tpl       | varchar(50)      | NO   |     |         |                |
// | read_tpl        | varchar(50)      | NO   |     |         |                |
// | is_applied      | tinyint(1)       | YES  |     | 0       |                |
// | is_subscribe    | tinyint(1)       | YES  |     | 0       |                |
// | status          | tinyint(1)       | YES  |     | 1       |                |
// | sort            | int(11)          | YES  |     | 0       |                |
// | member_id       | int(11) unsigned | YES  |     | 0       |                |
// | create_time     | int(11) unsigned | YES  |     | 0       |                |
// | update_time     | int(11) unsigned | YES  |     | 0       |                |
// | delete_time     | int(11) unsigned | YES  |     | 0       |                |
// | is_attached     | tinyint(1)       | YES  |     | 0       |                |
// | name            | varchar(50)      | YES  |     |         |                |
// +-----------------+------------------+------+-----+---------+----------------+
namespace app\common\model;

use think\facade\Config;
use think\facade\Cache;
use app\common\model\Base;
use app\common\validate\Category as Validate;

class Category extends Base
{
    public function parent()
    {
        return $this->belongsTo('Category', 'parent_id');
    }

    public function children()
    {
        return $this->hasMany('Category', 'parent_id');
    }

    public function articles(){
        return $this->hasMany('Article', 'second_category_id');
    }

    /**
     * 与AuthGroup BelongsTo关联设置
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @return   array              [description]
     */
    public function pcBanner()
    {
        return $this->belongsTo('Upload', 'pc_banner_id')->bind([
                'pc_banner_path'  => 'save_path',
            ]);
    }

    /**
     * 与AuthGroup BelongsTo关联设置
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @return   array              [description]
     */
    public function wapBanner()
    {
        return $this->belongsTo('Upload', 'wap_banner_id')->bind([
                'wap_banner_path'  => 'save_path',
            ]);
    }

    /**
     * 与AuthGroup BelongsTo关联设置
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @return   array              [description]
     */
    public function member()
    {
        return $this->belongsTo('Member')->bind([
                'member_name'  => 'name',
            ]);
    }

    /**
     * 列表搜索方法
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @param    array              $param     搜索参数
     * @param    integer            $page_rows 每页显示数量
     * @return   Paginate
     */
    public function childrenSelect($param)
    {
        $map = $this->parseSearchParam($param);
        $order_type = 'default';
        if(isset($param['order_type'])){
            $order_type = $param['order_type'];
        }
        $order_str = $this->queryOrderStr($order_type);
        if(isset($param['select_with'])){
            if($param['select_with'] == 'all'){
                $that = $this->with($param['pc_banner,member,children']);
            }else{
                $that = $this->with($param['select_with']);
            }
        }else{
            $that = $this;
        }
        $list = $that->where($map)->order($order_str)->select();
        return $list;
    }

    /**
     * 树状结构
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-12
     * @param    boolean            $only_active 是否只显示status=1的记录
     * @return   array                           [description]
     */
    public function treeView($only_active = true){
        $cache_key = $this->treeCacheKey($only_active);
        $tree = Cache::get($cache_key);
        if(!empty($tree)){
            return $tree;
        }

        $map = [];
        $map['parent_id'] = 0;
        if($only_active){
            $map['status'] = 1;
        }
        $tree = [];
        // 一级栏目显示字段
        $root_fields = $this->treeRootNodeFields();
        // 二级栏目分类显示字段
        $child_fields = [
            'id', 'title', 'is_subscribe', 'is_attached', 'is_applied'
        ];
        $order_str = $this->queryOrderStr('default');
        $list = $this->with('pc_banner')->field($root_fields)->where($map)->order($order_str)->select();
        foreach ($list as $k_r => $item) {
            $map['parent_id'] = $item['id'];
            $children = $this->field($child_fields)->where($map)->order($order_str)->select();
            $item_children = [];
            $default_second_id = 0;
            foreach ($children as $k_c => $child) {
                $item_children[$child['id']] = $child;
                if($default_second_id == 0){
                    $default_second_id = $child['id'];
                }
            }
            $item['children'] = $item_children;
            $item['default_second_category_id'] = $default_second_id;

            if(empty($item['slug'])){
                $tree_key = 'cat_'.$item['id'];
            }else{
                $tree_key = $item['slug'];
            }
            $tree[$tree_key] = $item;
        }

        Cache::set($cache_key, $tree);
        return $tree;
    }

    /**
     * TreeView的空根结点元素
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-26
     * @return   [type]             [description]
     */
    public function emptyTreeRootNode(){
        $item = [];
        $fields = $this->treeRootNodeFields();
        foreach ($fields as $key => $name) {
            if(strpos($name, 'id') !== false){
                $val = 0;
            }else{
                $val = '';
            }
            $item[$name] = $val;
        }
        return $item;
    }

    /**
     * 添加或更新记录
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @param    array              $data 表单提交数据
     * @param    integer            $id   主键ID
     * @return   array                    更新结果
     */
    public function createOrUpdate($data, $id = 0)
    {
        $res = ['status' => false, 'data' => [], 'msg' => "添加或更新分类失败"];
        if($id > 0){
            $data['id'] = $id;
        }

        $scene_name = 'child';
        if(isset($data['name']) && !empty($data['name'])){
            $data['name'] = strtoupper($data['name']);
            $scene_name = 'parent';
        }
        $validate = new Validate;
        if(!$validate->scene($scene_name)->check($data)){
            $res['msg'] = $validate->getError();
            return $res;
        }

        if(isset($data['id']) && $data['id'] > 0){
            $item = $this->where('id', $data['id'])->find();
        }else{
            $item = [];
        }
        if(empty($item)){
            $is_update = false;
            $msg = '添加分类成功';
        }else{
            $is_update = true;
            $msg = '更新分类成功';
            $data['id'] = $item['id'];
        }
        $this->data($data)->isUpdate($is_update)->allowField(true)->save();

        // 清除旧的缓存数据
        $this->clearAllCache();

        $res = [
            'status' => true,
            'msg' => $msg,
            'data' => ['id' => $this->id],
        ];
        return $res;
    }

    /**
     * 根据菜单名或标题创建/更新记录
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @param    array              $data [description]
     * @return   array                    [description]
     */
    public function findOrCreate($data)
    {
        $res = ['status' => false, 'data' => [], 'msg' => "添加或更新分类失败"];

        if(!isset($data['title'])){
            $res['msg'] = '分类标题不能为空';
            return $res;
        }
        $item = $this->where('title', $data['title'])->find();
        if(!empty($item)){
            $res = [
                'status' => true,
                'data' => ['id' => $item['id']],
                'msg' => '查找到该分类记录',
            ];
            return $res;
        }

        return $this->createOrUpdate($data);
    }

    /**
     * 验证是否可以删除当前记录
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-12
     * @param    [type]             $id [description]
     * @return   [type]                 [description]
     */
    protected function canDeleteItem($id){
        $res = ['status' => false, 'msg' => '不可以删除当前分类'];
        $id = intval($id);
        $item = $this->where('id', $id)->find();
        if(empty($item)){
            $res['msg'] = '删除分类不存在';
            return $res;
        }else if($item['parent_id'] == 0){
            $res['msg'] = '不能删除栏目分类';
            return $res;
        }
        if($item->children()->count()){
            $res['msg'] = '不能删除有子分类的分类';
            return $res;
        }
        if($item->articles()->count()){
            $res['msg'] = '不能删除有文章记录的分类';
            return $res;
        }

        $res = ['status' => true, 'msg' => '可以删除当前分类'];
        return $res;
    }

    /**
     * 排序后的操作
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-11
     * @return   boolean                   [description]
     */
    protected function afterResort(){
        // 清除旧的缓存数据
        $this->clearAllCache();
        return true;
    }

    /**
     * 清除所有旧的缓存数据
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-12
     * @return   boolean           [description]
     */
    public function clearAllCache(){
        $status = [true, false];
        foreach ($status as $key => $val) {
            $cache_key = $this->treeCacheKey($val);
            Cache::rm($cache_key);
        }
        return true;
    }

    /**
     * treeView方法的缓存Key
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-12
     * @param    [type]             $only_active [description]
     * @return   [type]                          [description]
     */
    private function treeCacheKey($only_active){
        if($only_active){
            $suffix = 'true';
        }else{
            $suffix = 'all';
        }
        return 'category_tree_'.$suffix;
    }

    /**
     * 转化查询条件
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @param    array              $param [description]
     * @return   array                     [description]
     */
    private function parseSearchParam($param)
    {
        $map = [];
        foreach ($param as $key => $value) {
            if(!is_array($value)){
                $value = trim($value);
            }
            switch ($key) {
            case "parent_id":
                if(intval($value) < 0){
                    $value = -1;
                }
                $map[] = ["parent_id", '=', $value];
                break;
            case "keyword":
                if(empty($value)){
                    continue;
                }else{
                    $keyword = "%{$value}%";
                }
                $map[] = ["title", "like", $keyword];
                break;
            }
        }
        return $map;
    }

    /**
     * 搜索排序方式
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-07
     * @param    string             $param 排序方式
     * @return   string                    [description]
     */
    protected function queryOrderStr($order_type = '')
    {
        switch ($order_type) {
        case 'id_asc':
            $str = 'id ASC';
            break;
        default:
            $str = 'sort ASC, id DESC';
            break;
        }
        return $str;
    }

    /**
     * TreeView的根结点查询字段
     * @Author   zhanghong(Laifuzi)
     * @DateTime 2018-06-26
     * @return   [type]             [description]
     */
    private function treeRootNodeFields(){
        return [
            'id', 'name', 'title', 'slug', 'pc_banner_id',
            'seo_description', 'seo_keywords',
        ];
    }
}
